package com.dilean.impl.dao;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.dilean.api.dao.AbstractDAO;
import com.dilean.api.model.AbstractEntity;

@Repository
@Transactional(readOnly = true)
public class AbstractDAOImpl<T extends AbstractEntity> implements AbstractDAO<T> {

	protected EntityManager em = null;

    @PersistenceContext
    public void setEntityManager(EntityManager em)
    {
        this.em = em;
    }
    

	@SuppressWarnings("unchecked")
	private Class<T> getEntityClass() {
		Class<T> clazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		try 
		{
			clazz = (Class<T>) Class.forName("com.dilean.impl.model."+ clazz.getSimpleName()+"Impl");
	    	return clazz;
		} 
		catch (ClassNotFoundException e) 
		{
			throw new RuntimeException(e);
		}
    }
    
	@Override
	public T findById(Integer id) {
			return em.find(getEntityClass(), id); 
	}

	@SuppressWarnings("unchecked")
	@Override
	public Collection<T> findByName(String entityName) {
		return em.createQuery("from "+getEntityClass().getSimpleName()+" p where p.name = :name order by p.name")
	            .setParameter("name", entityName).getResultList();
	    
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public Collection<T> findAll() {
		return em.createQuery("from "+getEntityClass().getSimpleName()+" p order by p.id").getResultList();
	}

	@Override
	@Transactional(readOnly = false)
	public T save(T entity) {
		return em.merge(entity);
	}

	@Override
    @Transactional(readOnly = false)
	public void delete(T entity) {
		em.remove(findById(entity.getId()));
	}

}
